{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用MindSpore实现简单线性函数拟合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 概述\n",
    "\n",
    "回归问题算法通常是利用一系列属性来预测一个值，预测的值是连续的。例如给出一套房子的一些特征数据，如面积、卧室数等等来预测房价，利用最近一周的气温变化和卫星云图来预测未来的气温情况等。如果一套房子实际价格为500万元，通过回归分析的预测值为499万元，则认为这是一个比较好的回归分析。在机器学习问题中，常见的回归分析有线性回归、多项式回归、逻辑回归等。本例子介绍线性回归算法，并通过MindSpore进行线性回归AI训练体验。\n",
    "\n",
    "整体流程如下：\n",
    "\n",
    "1. 生成数据集\n",
    "2. 定义训练网络\n",
    "3. 定义前向传播网络与反向传播网络并关联\n",
    "4. 拟合过程可视化准备\n",
    "5. 执行训练\n",
    "\n",
    "> 本文档适用于CPU、GPU和Ascend环境。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 环境准备\n",
    "\n",
    "设置MindSpore运行配置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.002170Z",
     "start_time": "2020-09-14T10:38:39.441746Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import context\n",
    "\n",
    "context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`GRAPH_MODE`：图模式。\n",
    "\n",
    "`device_target`：设置MindSpore的训练硬件为CPU。\n",
    "\n",
    "> 本教程代码依赖`matplotlib`第三方支持包，可使用命令`pip install matplotlib`安装。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生成数据集\n",
    "\n",
    "### 定义数据集生成函数\n",
    "\n",
    "`get_data`用于生成训练数据集和测试数据集。由于拟合的是线性数据，假定要拟合的目标函数为：$f(x)=2x+3$，那么我们需要的训练数据集应随机分布于函数周边，这里采用了$f(x)=2x+3+noise$的方式生成，其中`noise`为遵循标准正态分布规律的随机数值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.007850Z",
     "start_time": "2020-09-14T10:38:40.003169Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def get_data(num, w=2.0, b=3.0):\n",
    "    for _ in range(num):\n",
    "        x = np.random.uniform(-10.0, 10.0)\n",
    "        noise = np.random.normal(0, 1)\n",
    "        y = x * w + b + noise\n",
    "        yield np.array([x]).astype(np.float32), np.array([y]).astype(np.float32)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用`get_data`生成50组测试数据，并可视化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.355635Z",
     "start_time": "2020-09-14T10:38:40.009930Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "eval_data = list(get_data(50))\n",
    "x_target_label = np.array([-10, 10, 0.1])\n",
    "y_target_label = x_target_label * 2 + 3\n",
    "x_eval_label,y_eval_label = zip(*eval_data)\n",
    "\n",
    "plt.scatter(x_eval_label, y_eval_label, color=\"red\", s=5)\n",
    "plt.plot(x_target_label, y_target_label, color=\"green\")\n",
    "plt.title(\"Eval data\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上图中绿色线条部分为目标函数，红点部分为验证数据`eval_data`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义数据增强函数\n",
    "\n",
    "使用MindSpore的数据增强函数，将数据进行增强操作，操作解释如下：\n",
    "\n",
    "- `ds.GeneratorDataset`：将生成的数据转换为MindSpore的数据集，并且将生成的数据的x，y值存入到`data`和`label`的数组中。\n",
    "- `batch`：将`batch_size`个数据组合成一个batch。\n",
    "- `repeat`：将数据集数量倍增。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.390782Z",
     "start_time": "2020-09-14T10:38:40.356644Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import dataset as ds\n",
    "\n",
    "def create_dataset(num_data, batch_size=16, repeat_size=1):\n",
    "    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['data','label'])\n",
    "    input_data = input_data.batch(batch_size)\n",
    "    input_data = input_data.repeat(repeat_size)\n",
    "    return input_data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用数据集增强函数生成训练数据，并查看训练数据的格式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.435708Z",
     "start_time": "2020-09-14T10:38:40.391790Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The dataset size of ds_train: 100\n",
      "dict_keys(['data', 'label'])\n",
      "The x label value shape: (16, 1)\n",
      "The y label value shape: (16, 1)\n"
     ]
    }
   ],
   "source": [
    "data_number = 1600\n",
    "batch_number = 16\n",
    "repeat_number = 1\n",
    "\n",
    "ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number) \n",
    "print(\"The dataset size of ds_train:\", ds_train.get_dataset_size())\n",
    "dict_datasets = ds_train.create_dict_iterator().get_next()\n",
    "\n",
    "print(dict_datasets.keys())\n",
    "print(\"The x label value shape:\", dict_datasets[\"data\"].shape)\n",
    "print(\"The y label value shape:\", dict_datasets[\"label\"].shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过定义的`create_dataset`将生成的1600个数据增强为了100组shape为16x1的数据集。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义训练网络\n",
    "\n",
    "在MindSpore中使用`nn.Dense`生成单个数据输入，单个数据输出的线性函数模型：\n",
    "\n",
    "$$f(x)=wx+b\\tag{1}$$\n",
    "\n",
    "并使用Normal算子随机初始化权重$w$和$b$。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.441532Z",
     "start_time": "2020-09-14T10:38:40.436780Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore.common.initializer import Normal\n",
    "from mindspore import nn\n",
    "\n",
    "class LinearNet(nn.Cell):\n",
    "    def __init__(self):\n",
    "        super(LinearNet, self).__init__()\n",
    "        self.fc = nn.Dense(1, 1, Normal(0.02), Normal(0.02))\n",
    "        \n",
    "    def construct(self, x):\n",
    "        x = self.fc(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调用网络查看初始化的模型参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.456400Z",
     "start_time": "2020-09-14T10:38:40.442544Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Parameter (name=fc.weight, value=Tensor(shape=[1, 1], dtype=Float32, value=\n",
      "[[-1.08274454e-02]])), Parameter (name=fc.bias, value=Tensor(shape=[1], dtype=Float32, value= [-1.08274454e-02]))]\n"
     ]
    }
   ],
   "source": [
    "net = LinearNet()\n",
    "model_params = net.trainable_params()\n",
    "print(model_params)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "初始化网络模型后，接下来将初始化的网络函数和训练数据集进行可视化，了解拟合前的模型函数情况。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.607733Z",
     "start_time": "2020-09-14T10:38:40.457985Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mindspore import Tensor\n",
    "\n",
    "x_model_label = np.array([-10, 10, 0.1])\n",
    "y_model_label = (x_model_label * Tensor(model_params[0]).asnumpy()[0][0] + \n",
    "                 Tensor(model_params[1]).asnumpy()[0])\n",
    "\n",
    "plt.axis([-10, 10, -20, 25])\n",
    "plt.scatter(x_eval_label, y_eval_label, color=\"red\", s=5)\n",
    "plt.plot(x_model_label, y_model_label, color=\"blue\")\n",
    "plt.plot(x_target_label, y_target_label, color=\"green\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从上图中可以看出，蓝色线条的初始化模型函数与绿色线条的目标函数还是有较大的差别的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义前向传播网络与反向传播网络并关联"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来需要定义模型的损失函数，这里采用均方差的方法用于判断拟合的效果如何，即均方差值越小，拟合的效果越好，其损失损失函数公式为：\n",
    "\n",
    "$$J(w)=\\frac{1}{2m}\\sum_{i=1}^m(h(x_i)-y^{(i)})^2\\tag{2}$$\n",
    "\n",
    "假设训练数据第$i$个数据为$(x_i,y^{(i)})$，公式2中的参数解释如下：\n",
    "\n",
    "- $J(w)$为损失值。\n",
    "\n",
    "- $m$为样本数据的数量，本例中$m$的值为`batch_number`。\n",
    "\n",
    "- $h(x_i)$为第$i$个数据的$x_i$值代入模型网络（公式1）后的预测值。\n",
    "\n",
    "- $y^{(i)}$为第$i$个数据中的$y^{(i)}$值（label值）。\n",
    "\n",
    "### 定义前向传播网络\n",
    "\n",
    "前向传播网络包含两个部分，其中：\n",
    "\n",
    "1. 将参数带入到模型网络中得出预测值。\n",
    "2. 使用预测值和训练数据计算出loss值。\n",
    "\n",
    "在MindSpore中使用如下方式实现。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.615390Z",
     "start_time": "2020-09-14T10:38:40.609289Z"
    }
   },
   "outputs": [],
   "source": [
    "net = LinearNet()\n",
    "net_loss = nn.loss.MSELoss()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义反向传播网络\n",
    "\n",
    "反向传播网络的目标是不断变换权重值，使得loss值取得最小值，一般的在线性网络中采用权重更新公式：\n",
    "\n",
    "$$w_{t}=w_{t-1}-\\alpha\\frac{\\partial{J(w_{t-1})}}{\\partial{w}}\\tag{3}$$\n",
    "\n",
    "公式3参数解释：\n",
    "\n",
    "- $w_{t}$为迭代后的权重值。\n",
    "- $w_{t-1}$为迭代前的权重值。\n",
    "- $\\alpha$为学习率。\n",
    "- $\\frac{\\partial{J(w_{t-1}\\ )}}{\\partial{w}}$为损失函数对权重$w_{t-1}$的微分。\n",
    "\n",
    "函数中所有的权重值更新完成后，将值传入到模型函数中，这个过程就是反向传播过程，实现此过程需要使用MindSpore中的优化器函数，如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.629217Z",
     "start_time": "2020-09-14T10:38:40.616392Z"
    }
   },
   "outputs": [],
   "source": [
    "opt = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 关联前向和反向传播网络\n",
    "\n",
    "定义完成前向传播和反向传播后，在MindSpore中需要调用`Model`函数，将前面定义的网络，损失函数，优化器函数关联起来，使之变成完整的计算网络。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.645718Z",
     "start_time": "2020-09-14T10:38:40.630789Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import Model\n",
    "\n",
    "model = Model(net, net_loss, opt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 拟合过程可视化准备\n",
    "\n",
    "### 定义绘图函数\n",
    "\n",
    "为了使得整个训练过程更容易理解，需要将训练过程的测试数据、目标函数和模型网络进行可视化，这里定义了可视化函数，将在每个step训练结束后调用，展示模型网络的拟合过程。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.680586Z",
     "start_time": "2020-09-14T10:38:40.646738Z"
    }
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import time\n",
    "\n",
    "def plot_model_and_datasets(net, eval_data):\n",
    "    weight = net.trainable_params()[0]\n",
    "    bias = net.trainable_params()[1]\n",
    "    x = np.arange(-10, 10, 0.1)\n",
    "    y = x * Tensor(weight).asnumpy()[0][0] + Tensor(bias).asnumpy()[0]\n",
    "    x1, y1 = zip(*eval_data)\n",
    "    x_target = x\n",
    "    y_target = x_target * 2 + 3\n",
    "    \n",
    "    plt.axis([-11, 11, -20, 25])\n",
    "    plt.scatter(x1, y1, color=\"red\", s=5)\n",
    "    plt.plot(x, y, color=\"blue\")\n",
    "    plt.plot(x_target, y_target, color=\"green\")\n",
    "    plt.show()\n",
    "    time.sleep(0.2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义回调函数\n",
    "\n",
    "MindSpore提供的工具，可对模型训练过程进行自定义控制，这里在`step_end`中调用可视化函数，展示拟合过程。更多的使用可参考[官网说明](https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/custom_debugging_info.html#callback)\n",
    "\n",
    "- `display.clear_output`：清除打印内容，实现动态拟合效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.706063Z",
     "start_time": "2020-09-14T10:38:40.681635Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython import display\n",
    "from mindspore.train.callback import Callback\n",
    "\n",
    "class ImageShowCallback(Callback):\n",
    "    def __init__(self, net, eval_data):\n",
    "        self.net = net\n",
    "        self.eval_data = eval_data\n",
    "        \n",
    "    def step_end(self, run_context):\n",
    "        plot_model_and_datasets(self.net, self.eval_data)\n",
    "        display.clear_output(wait=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 执行训练\n",
    "\n",
    "完成以上过程后，可以使用训练数`ds_train`对模型训练，这里调用`model.train`进行，其中参数解释：\n",
    "\n",
    "- `epoch`：训练迭代的整个数据集的次数。\n",
    "- `ds_train`：训练数据集。\n",
    "- `callbacks`：训练过程中需要调用的回调函数。\n",
    "- `dataset_sink_model`：数据集下沉模式，支持Ascend、GPU计算平台，本例为CPU计算平台设置为False。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:47:22.917679Z",
     "start_time": "2020-09-14T10:38:40.707096Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parameter (name=fc.weight, value=[[2.0398366]]) \n",
      "Parameter (name=fc.bias, value=[3.071223])\n"
     ]
    }
   ],
   "source": [
    "\n",
    "from mindspore.train.callback import LossMonitor\n",
    "\n",
    "epoch = 1\n",
    "imageshow_cb = ImageShowCallback(net, eval_data)\n",
    "model.train(epoch, ds_train, callbacks=[imageshow_cb], dataset_sink_mode=False)\n",
    "\n",
    "plot_model_and_datasets(net,eval_data)\n",
    "print(net.trainable_params()[0], \"\\n%s\" % net.trainable_params()[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T04:00:18.787349Z",
     "start_time": "2020-09-14T04:00:18.784236Z"
    }
   },
   "source": [
    "训练完成后打印出最终模型的权重参数，其中weight接近于2.0，bias接近于3.0，模型训练完成，符合预期。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本次体验我们了解了线性拟合的算法原理，并在MindSpore框架下实现了相应的算法定义，了解了线性拟合这类的线性回归模型在MindSpore中的训练过程，并最终拟合出了一条接近目标函数的模型函数。另外有兴趣的可以调整数据集的生成区间从（-10,10）扩展到（-100,100），看看权重值是否更接近目标函数；调整学习率大小，看看拟合的效率是否有变化；当然也可以探索如何使用MindSpore拟合$f(x)=ax^2+bx+c$这类的二次函数或者更高次的函数。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MindSpore-1.0.1",
   "language": "python",
   "name": "mindspore-1.0.1"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
